#ifndef LECTEURPHRASESIMPLE_H_
#define LECTEURPHRASESIMPLE_H_

#include "LecteurSymbole.h"

/*! \file LecteurPhraseSimple.h
    \brief La spécification de la classe LecteurPhraseSimple
    
    Décrit la liste des méthodes et attributs associés à la classe LecteurPhraseSimple
    \author lazzamar
    \date 16/12/2012
 */
/*! \class LecteurPhraseSimple
    \brief La classe représentant le lecteur de base de phrases du langage.
    
    Cette classe permet de lire les phrases du langage. Elle contient des
 méthodes pour analyser syntaxiquement étape par étape la grammaire du langage.
 Ces méthodes sont accompagnée de méthodes de test pour savoir quelle méthode
 d'analyse utiliser.
 Ces méthodes étant privées, elle ne sont pas documentées.
 La méthode suivante déclenche l'analyse :
    \li analyse
*/

class LecteurPhraseSimple {
public:
	/*! \fn LecteurPhraseSimple(string nomFich);
		\brief Constructeur de la classe LecteurPhraseSimple

	 Ce constructeur construit le lecteur de symbole en ouvrant le fichier (en
	 appelant le constructeur de ls) pour vérifier la syntaxe du programme.
		\param string nomFich - le nom du fichier à ouvrir
	*/
    LecteurPhraseSimple(string nomFich); // Construit un lecteur de phrase pour vérifier
                                         // la syntaxe du programme dans le fichier nomFich

	/*! \fn void analyse();
		\brief Analyse le programme.

	 Si le contenu du fichier est conforme à la grammaire, le programme se termine
	 normalement en affichant "Syntaxe Correcte". Sinon une exception est levée.
	*/
    void analyse();   // Si le contenu du fichier est conforme à la grammaire,
                      // cette méthode se termine normalement et affiche un message "Syntaxe correcte".
                      // Sinon, le programme sera interrompu (exit).
        	
private:
	/*! \var LecteurSymbole ls
		\brief Le lecteur de symbole.

	 Contient le lecteur de symbole utilisé pour l'analyse.
	*/
    LecteurSymbole ls;  // le lecteur de symboles utilisé pour lyser le fichier		

    // implémentation de la grammaire
    void programme();   //   <programme> ::= debut <seqInst> fin <EOF>
    void seqInst();	    //     <seq_ins> ::= <inst> ; { <inst> ; }
    void inst();	    //        <inst> ::= <affectation> | <instSi> | <instSelon> | <instTq> | <instRepeter> | <instPour> | <instLire> | <instEcrire>
    void affectation();	// <affectation> ::= <variable> = <expression>
    void expression();	//  <expression> ::= <terme> { <opAdd> <terme> }
	void terme();		//       <terme> ::= <facteur> {<opMult> <facteur>}
    void facteur();     //     <facteur> ::= <entier>  |  <variable>  | <chaine> | <opUnaire> <expBool>  |  ( <expBool> )
	void expBool();		//	   <expBool> ::= <termBool> { <opOu> <termBool> }
	void termBool();	//	  <termBool> ::= <relation> { <opEt> <relation> }
	void relation();	//	  <relation> ::= <expression> { <opRel> <expression> }
	void opEt();		//		  <opEt> ::= et
	void opOu();		//		  <opOu> ::= ou
	void opRel();		//		 <opRel> ::= == | != | < | <= | > | >=
    void opAdd();		//       <opAdd> ::= + | -
	void opMult();		//		<opMult> ::= * | /
	void opUnaire();	//	  <opUnaire> ::= - | non
	
	void instSi();		//		<instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> }
						//					[ sinon <seqInst> ] finsi
	void instSelon();	//	 <instSelon> ::= selon ( <variable> )
						//					cas <expression> : <seqInst>
						//					{ cas <expression> : <seqInst> }
						//					[ defaut : <seqInst> ]
						//					finselon
	
	void instTq();		//		<instTq> ::= tantque ( <expBool> ) <seqInst> fintantque
	void instRepeter();	// <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
	void instPour();	//	  <instPour> ::= pour ( <affectation> ; <expBool> ; <inst> ) faire
						//					<seqInst> finfaire
	
	void instLire();	//	  <instLire> ::= lire ( <variable> )
	void instEcrire();	//	<instEcrire> ::= ecrire ( <expression> )

    // outils pour se simplifier l'analyse syntaxique
    void testerSymCour (string ch);  // si symbole courant != ch, erreur : on arrete le programme, sinon rien
    void sauterSymCour (string ch);  // si symbole courant == ch, on passe au symbole suivant, sinon erreur : on arrete
    void erreur (string mess);      // affiche les message d'erreur mess et arrete le programme
	
	
	// méthodes de test
	inline bool isVariable(){return (ls.getSymCour()=="<VARIABLE>");}
	inline bool isEntier(){return (ls.getSymCour()=="<ENTIER>");}
	inline bool isChaine(){return (ls.getSymCour()=="<CHAINE>");}
	inline bool isOpEt(){return (ls.getSymCour()=="et");}
	inline bool isOpOu(){return (ls.getSymCour()=="ou");}
	inline bool isOpRel(){return (ls.getSymCour()=="=="
			|| ls.getSymCour()=="!=" || ls.getSymCour()=="<="
			|| ls.getSymCour()==">=" || ls.getSymCour()==">"
			|| ls.getSymCour()=="<");}
	inline bool isOpAdd(){return (ls.getSymCour()=="+" || ls.getSymCour()=="-");}
	inline bool isOpMult(){return (ls.getSymCour()=="*" || ls.getSymCour()=="/");}
	inline bool isOpUnaire(){return (ls.getSymCour()=="-" || ls.getSymCour()=="non");}
	inline bool isInstSi(){return (ls.getSymCour()=="si");}
	inline bool isInstSelon(){return (ls.getSymCour()=="selon");}
	inline bool isInstTq(){return (ls.getSymCour()=="tantque");}
	inline bool isInstRepeter(){return (ls.getSymCour()=="repeter");}
	inline bool isInstPour(){return (ls.getSymCour()=="pour");}
	inline bool isInstLire(){return (ls.getSymCour()=="lire");}
	inline bool isInstEcrire(){return (ls.getSymCour()=="ecrire");}
};

#endif /* LECTEURPHRASESIMPLE_H_ */
